// LemCoop
// Copyright (C) 2013  Oliver Naumann <bldrax@gmail.com>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef LEMC_GAMEENGINE_H
#define LEMC_GAMEENGINE_H

#include "WindowsIncludes.h"
#include <allegro5/allegro.h>

#include "../gamestates/gamestate.h"
#include "system.h"

class GameEngine
{
private:
	// Contains the current game state.
	GameState* m_state;

	// Contains the next game state to be set.
	GameState* m_next_state;

	float m_timing_factor;
	ALLEGRO_TIMER* m_timing_factor_timer;

	// Contains the input events.
	ALLEGRO_EVENT_QUEUE* m_input_queue;

	// A bitmap for everything that has priority do be drawn over everything else.
	ALLEGRO_BITMAP* m_top_layer;

	// True if the game should end.
	bool m_end_game;

	//DEBUG
	ALLEGRO_FONT* m_fps_font;

	/*
	* Jumps to the next gamestate.
	*
	* @param new_state The next state.
	*/
	void ChangeGameState();

public:
	/*
	* The contructor just sets the state and next_state to NULL and initializes allegro for us.
	*/
	GameEngine();

	/*
	* Deletes the current state and does all cleanup before the system can shutdown.
	*/
	~GameEngine();

	/*
	* Sets the next gamestate. As soon as this function was called, the GameEngine realizes
	* that because m_next_state is not the nullptr anymore. It then changes the state
	* by itself on the next Update-cycle.
	*
	* @param new_state The next state.
	*/
	void SetNextState(GameState* new_state);

	void CheckState();

	void HandleInput();

	/*
	* Updates the game by calling the update method of the current gamestate.
	*/
	void Update();

	/*
	* Draws the game by calling the draw method of the current gamestate.
	*/
	void Draw();

	bool end_game() { return m_end_game; }
	void set_end_game(bool end_game) { m_end_game = end_game; }
	ALLEGRO_BITMAP* top_layer() { return m_top_layer; }
};

#endif